;;; init-completion.el -- Configuration for completing -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:

(with-eval-after-load 'dabbrev
  (setq dabbrev-ignored-buffer-regexps '("\\`[ *]" "\\.\\(?:pdf\\|jpe?g\\|png\\)\\'")))


(add-hook 'after-init-hook 'global-corfu-mode)
(with-eval-after-load 'corfu
  (require 'cape)

  (setq corfu-auto t)
  (setq corfu-cycle t)
  (setq corfu-auto-prefix 1)
  (setq corfu-auto-delay 0.1)
  (setq corfu-quit-at-boundary 'separator)
  (setq global-corfu-modes '((not eshell-mode) t))
  (setq completion-cycle-threshold 3)

  (define-key corfu-map (kbd "<escape>") #'corfu-quit)
  (define-key corfu-map (kbd "M-k") #'corfu-previous)
  (define-key corfu-map (kbd "TAB") #'corfu-next)
  (define-key corfu-map [tab] #'corfu-next)
  (define-key corfu-map (kbd "S-TAB") #'corfu-previous)
  (define-key corfu-map [backtab] #'corfu-previouso)

  ;; Add other completion sources, order is important
  (add-to-list 'completion-at-point-functions #'cape-file)
  (add-to-list 'completion-at-point-functions #'cape-dabbrev)
  (add-to-list 'completion-at-point-functions #'cape-keyword)
  (add-to-list 'completion-at-point-functions #'cape-abbrev)

  ;; Completing with Corfu in the minibuffer
  (defun corfu-enable-always-in-minibuffer ()
    "Enable Corfu in the minibuffer if Vertico/Mct are not active."
    (unless (or (bound-and-true-p mct--active)
                (bound-and-true-p vertico--input)
                (eq (current-local-map) read-passwd-map))
      ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion
      (setq-local corfu-echo-delay nil ;; Disable automatic echo and popup
                  corfu-popupinfo-delay nil)
      (corfu-mode 1)))
  (add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1)

  ;; Transfer completion to the minibuffer
  (defun corfu-move-to-minibuffer ()
    (interactive)
    (pcase completion-in-region--data
      (`(,beg ,end ,table ,pred ,extras)
       (let ((completion-extra-properties extras)
             completion-cycle-threshold completion-cycling)
         (consult-completion-in-region beg end table pred)))))
  (keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer)
  (add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer)

  ;; Additional movement commands
  (defun corfu-beginning-of-prompt ()
    "Move to beginning of completion input."
    (interactive)
    (corfu--goto -1)
    (goto-char (car completion-in-region--data)))

  (defun corfu-end-of-prompt ()
    "Move to end of completion input."
    (interactive)
    (corfu--goto -1)
    (goto-char (cadr completion-in-region--data)))

  (define-key corfu-map (kbd "M-b") #'corfu-beginning-of-prompt)
  (define-key corfu-map (kbd "M-f") #'corfu-end-of-prompt)


  ;; corfu extensions setting
  (add-hook 'corfu-mode-hook 'corfu-history-mode)
  (add-to-list 'savehist-additional-variables 'corfu-history)

  (define-key corfu-map "\M-q" #'corfu-quick-complete)
  (define-key corfu-map "\C-q" #'corfu-quick-exit)

  (add-hook 'corfu-mode-hook 'corfu-echo-mode)

  (add-hook 'corfu-mode-hook #'corfu-popupinfo-mode)
  )

(with-eval-after-load 'cape

  (defvar ctrlwei-cape-map (make-sparse-keymap)
    "Keybinding for `cape")
  (global-set-key (kbd "M-c") ctrlwei-cape-map)

  (define-key ctrlwei-cape-map "d" #'cape-dabbrev)
  (define-key ctrlwei-cape-map "f" #'cape-file)
  (define-key ctrlwei-cape-map "k" #'cape-dict))


(with-eval-after-load 'corfu-popupinfo
  (setq corfu-popupinfo-delay nil)
  (setq corfu-popupinfo-max-height 17)
  (define-key corfu-popupinfo-map (kbd "M-d") nil)
  (define-key corfu-popupinfo-map (kbd "M-;") #'corfu-popupinfo-documentation)
  (define-key corfu-popupinfo-map (kbd "<f2>") #'corfu-popupinfo-scroll-up)
  (define-key corfu-popupinfo-map (kbd "<f3>") #'corfu-popupinfo-scroll-down))


(with-eval-after-load 'elisp-mode
  (defun ctrlwei/setup-elisp-capf ()
    (setq-local completion-at-point-functions (list
                                               (cape-capf-super #'elisp-completion-at-point #'cape-dabbrev)
                                               'cape-file
                                               'cape-dict)))
  (add-hook 'emacs-lisp-mode-hook #'ctrlwei/setup-elisp-capf)
  (add-hook 'lisp-interaction-mode-hook #'ctrlwei/setup-elisp-capf))


(provide 'init-completion)
;;; init-completion.el ends here
